package net.freestu.sola.web.global;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

import net.freestu.sola.web.spider.ballerina.core.Spider;
import net.freestu.sola.web.util.FileManager;

/**
 * 线程池,负责把线程的创建，销毁。统计。
 * 
 * @author 秋刀鱼的滋味
 * 
 */
public class ThreadPool{

	//-----------
  private static ThreadPool  singleton=new ThreadPool ();		
  synchronized public static  ThreadPool  getInstance(){
				return singleton;
  }
	//-----------
  
 private Map themap;
 private int spidernum=0;//?考虑:是否将母蜘蛛作为蜘蛛总数量（暂时不）
 
  
  private ThreadPool(){

    themap=new HashMap();
    new Born(this).start();//这里自动执行繁殖程序。
  }
  
  
  /**
   * add thread to the pool of threads
   * @param str
   */
  public synchronized void add(String str){//#
	  
	  Spider t=new Spider(str);
	  themap.put(str,t);  
  }
  
  
  
  /**
   * remove thread which needed from the pool
   * @param str
   * @return Spider
   */
  public synchronized Spider remove(String str){//#
	  
	  return (Spider)themap.remove(str);	  
  }
  
  
  /**
   * 
   * @param str
   * @return
   */  
  public synchronized Spider get(String str){
	  
	  return (Spider)themap.get(str);
  }
  
  /**
   * judge whether there is a thread in the thread pool.
   * @param str
   */
  public synchronized boolean  exist(String str){//
	  
	  
	  return themap.containsKey(str);
  }
  
  /**
   * 统计由种子变成的蜘蛛的数量，而有些种子并不没有顺利演变成蜘蛛。所以种子数量一定小于蜘蛛的数量。
   * @return
   */
  public synchronized int numOfSpider(){
	  
	 return spidernum;
	  
  }
  
  
  /**
   * 由种子生成蜘蛛。
   */
  public synchronized void  createOneSpider(){
	  
	  spidernum++;
  }
  
  /**
   * 蜘蛛死亡.注意:蜘蛛死亡后，并不从themap中去掉记录。
   */
  public synchronized void dieOneSpider(){
	  spidernum--;
  }
  
  
  /**
   * 统计种子多少,(考虑当线程打断后，要不要将其从themap去掉)？
   * 去掉了就没有蜘蛛繁殖记忆效果了。
   * @return
   */
  public synchronized int numOfSeed(){
	  
	  return themap.size(); 
  }
	  
	  
  /**
   * 
   *     @param str=“cdut.edu.cn"
   */
  public synchronized void start(String str){//#
	//创建文件夹  
	get(str).start(); 
  }
  
  /**
   * 销毁指定的线程对象。这里的destory是这个不推荐使用的方法。不是个线程安全的方法。等会修改##
   * @param str
   */
  public synchronized void destory(String str){
	
	  
         //1.将销毁指定线程。
		 //(2.把将其从线程池中移除。)没有必要！
		 //3。将文件夹除去。（貌似也没得必要，保留网页）
	  //-------------------------------------------
	  //Spider spi=remove(str);这里没有必要将该线程从线程池中移除，
	  //只需要销毁线程就是了，这样会避免再回收该种子(同样不能下载首页的线程)。
	  
	  Spider spi=get(str);
	  FileManager.deleteDir(GlobleVar.EXEFOLDER+File.separator+"Crawl Folder",str);
	  try {
		  spi.stop();
	} catch (RuntimeException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}  
  }
  
  
  
  
  /**
   * 这是个内部类，主要是隐藏一些实现细节。背景线程。
   * 这个线程负责从ThreadPool中提取种子，然后生成Spider
   * @author 秋刀鱼的滋味
   */

  private class Born extends Thread{
  	
  	ThreadPool tp;
  	
  	public Born(ThreadPool tp) {
  		
  		this.tp=tp;
  		
  	}
    
  	
  	/**
  	 * 从队列中取出种子，然后进行繁殖。用循环
  	 * 这里用内部类实现背景线程而实现自动繁殖.
  	 */
  	public void run() {
  		
  		while(true){
  			SeedQueue sq=SeedQueue.getInstance();//这里只是返回一个引用而已，并不会有太大的性能消耗。
  				String str=sq.pop();
  				
  				if(null!=str){
    			  tp.add(str);//编程总结：这个地方可以可以将add和start合成一个方法。以实现更高层次的抽象。
                  tp.start(str);//启动。
  				}         
  	   }
    }
  }
  public static void main(String[] args){
	  
	  ThreadPool tp=ThreadPool.getInstance();
  }
}